#include <stdio.h>
#include <string.h>

#include "AC33Mxxx_conf.h"
#include "driver_header.h"
#include "test_header.h"
#include "AC33Mxxx_it.h"

#include "console.h"
#include "slib.h"




//#############################################################################
//#
//#
//#
//#############################################################################
void SPI_Test(void)
{
	char 	ch;
	int		service_flag; 
	int		cmd_not_supported; 
	int		disp_menu = 1; 
	
	cputs(">>>>> SPI Test <<<<<\r\n"); 


	//-----------------------------------------------------------------------
	// init variables
	//-----------------------------------------------------------------------
	service_flag = 1; 
	cmd_not_supported = 0; 
	InFlag = InCount = 0; 



	//-----------------------------------------------------------------------
	// init monitored gpio
	//-----------------------------------------------------------------------	
	HAL_MONITOR_OUTPUT_LOW(); 


	//########################################################
	// test body 
	//########################################################
	while (service_flag)
	{

		//-------------------------------------------------------------------
		// disp menu
		//-------------------------------------------------------------------
		if (disp_menu)
		{
			Disp_SPI_Menu(); 
			disp_menu = 0; 
		}


		
		cputs("\r\nSPI>"); 		


		//-------------------------------------------------------------------
		// clear command buffer
		//-------------------------------------------------------------------
		InData[0] = 0; 


		//-------------------------------------------------------------------
		// get command
		//-------------------------------------------------------------------
		for (;;)
		{
			ch = getstring(); 
			if (ch == ASCII_CARRIAGE_RETURN) break; 
		}

		cputs("\r\n"); 


		//------------------------------------------------------------------
		//  collection of services 
		//------------------------------------------------------------------
		if (InFlag)
		{
			if (!strncmp(InData, "exit", 4))
			{
				service_flag = 0; 
			}
			else if (!strncmp(InData, "init", 4))
			{
				cmd_not_supported = SPI_TEST_Init(InData); 
			}
			else if (!strncmp(InData, "test", 4))
			{
				cmd_not_supported = SPI_TEST_test(InData); 
			}
			else if (!strncmp(InData, "h", 1))
			{
				disp_menu = 1; 
			}
			else 
			{
				cmd_not_supported = 1; 
			}


			if (cmd_not_supported)
			{
				cmd_not_supported = 0; 
				cputs("This command is not supported...\r\n"); 
			}

		}

		InFlag = InCount = 0; 
	}

	cputs("SPI Test Exit...\r\n\r\n"); 
	InFlag = InCount = 0; 
}



/**
*****************************************************************************************************
* @ Name : Disp_SPI_Menu
*
*
*
*****************************************************************************************************
*/
void Disp_SPI_Menu (void)
{

	cprintf("	   \r\n");
	cprintf("==[SPI]============================\r\n"); 
	cprintf("command: init, test\r\n");
	cprintf("[h] for displaying menu again\r\n");
	cprintf("===================================\r\n\r\n"); 


}

/**
*****************************************************************************************************
* @ Name : SPI_TEST_Init 
*
*
*
*****************************************************************************************************
*/
int SPI_TEST_Init(char * cmd_string)
{

	HAL_MONITOR_OUTPUT_LOW(); 


	//===============================================================
	// SPI TEST #1 : SPI0 Interrupt-driven Transmission
	//===============================================================
#if 0	

	//SPI_TEST_Master_Setting(0, SPI_PORTSEL_NORMAL); 
	//SPI_TEST_Master_Setting(0, SPI_PORTSEL_STAR); 
	//SPI_TEST_Master_Setting(1, SPI_PORTSEL_NORMAL); 
	//SPI_TEST_Master_Setting(1, SPI_PORTSEL_STAR); 


	//SPI_TEST_Slave_Setting(1, SPI_PORTSEL_NORMAL); 
	SPI_TEST_Master_Setting(0, SPI_PORTSEL_NORMAL); 	
#endif 	


	//===============================================================
	// SPI TEST #2 : SPI0 = master, SPI1 = slave 
	//				SPI0 --> SPI1 : transmit three bytes
	//				SPI1 --> SPI0 : transmit three bytes
	//
	//
	// SPI TEST #3: SPI0 = master, SPI1 = slave
	//				SPI0 --> SPI1 : transmit three bytes
	//				SPI1 --> SPI0 : transmit three bytes
	//
	//===============================================================
#if 0	
	CSP_SPI_ConfigureGPIO(SPI1, SPI_SLAVE, SPI_PORTSEL_NORMAL); 
	CSP_SPI_ConfigureGPIO(SPI0, SPI_MASTER, SPI_PORTSEL_NORMAL); 


	SPI_TEST_Slave_Setting(1, SPI_PORTSEL_NORMAL); 	
	SPI_TEST_Master_Setting(0, SPI_PORTSEL_NORMAL); 	
#endif 	


	//===============================================================
	// SPI TEST #4 : SPI0 = slave, SPI1 = master 
	//				SPI1 --> SPI0 : transmit three bytes
	//				SPI0 --> SPI1 : transmit three bytes
	//
	//
	// SPI TEST #5: SPI0 = slave, SPI1 = master
	//				SPI1 --> SPI0 : transmit three bytes
	//				SPI0 --> SPI1 : transmit three bytes
	//
	//===============================================================
	CSP_SPI_ConfigureGPIO(SPI0, SPI_SLAVE, SPI_PORTSEL_NORMAL); 
	CSP_SPI_ConfigureGPIO(SPI1, SPI_MASTER, SPI_PORTSEL_NORMAL); 


	SPI_TEST_Slave_Setting(0, SPI_PORTSEL_NORMAL); 	
	SPI_TEST_Master_Setting(1, SPI_PORTSEL_NORMAL); 	
	


	
	cprintf("SPI Init\r\n"); 
	

	return (0);
}



/**
*****************************************************************************************************
* @ Name : SPI_TEST_test 
*
*
*
*****************************************************************************************************
*/
int SPI_TEST_test (char * cmd_string)
{

	//===============================================================
	// SPI TEST #1 : SPI0 Interrupt-driven Transmission
	//===============================================================
#if 0	
	UINT32	write_buf[8] = {0xA5, 0xA6, 0xA7, 0xA8,  0xA9, 0xAA, 0xAB, 0xAC}; 

	
	SPI_Write_Data (0, SPI_MASTER, write_buf, 3); 
	//SPI_Write_Data (1, SPI_MASTER, write_buf, 8); 
#endif 

	//===============================================================
	// SPI TEST #2 : SPI0 = master, SPI1 = slave 
	//				SPI0 --> SPI1 : transmit three bytes
	//				SPI1 --> SPI0 : transmit three bytes
	//
	// DISPLAY --> SPI1 RX data [slave]
	//===============================================================
#if 0	
	UINT32			master_tx_data[8] = {0xA5, 0xA6, 0xA7, 0xA8,  0xA9, 0xAA, 0xAB, 0xAC}; 
	UINT32			slave_tx_data[8] = {0x50, 0x51, 0x52, 0x53,  0x54, 0x55, 0x56, 0x57}; 
	UINT32			slave_rx_data[8]; 
	int				read_count; 
	int				i; 
	volatile int	delay; 
		

	SPI_TEST_Load_Slave_TX_Data (1, slave_tx_data, 3); 
	SPI_Write_Data (0, SPI_MASTER, master_tx_data, 3); 

	for (delay=0; delay<10000; delay++); 

	read_count = 5; 
	SPI_Read_Data (1, SPI_SLAVE, slave_rx_data, &read_count); 

	cprintf("read_count=%d\r\n", read_count);

	for (i=0; i<read_count; i++) cprintf("0x%04X, ", slave_rx_data[i]); 
	cprintf("\r\n"); 

#endif 


	//===============================================================
	// SPI TEST #3 : SPI0 = master, SPI1 = slave 
	//				SPI0 --> SPI1 : transmit three bytes
	//				SPI1 --> SPI0 : transmit three bytes
	//
	// DISPLAY --> SPI0 RX data [master] 
	//===============================================================
#if 0
	UINT32			master_tx_data[8] = {0xA5, 0xA6, 0xA7, 0xA8,  0xA9, 0xAA, 0xAB, 0xAC}; 
	UINT32			slave_tx_data[8] = {0x50, 0x51, 0x52, 0x53,  0x54, 0x55, 0x56, 0x57}; 
	UINT32			slave_rx_data[8]; 
	int 			read_count; 
	int 			i; 
	volatile int	delay; 
			
	
	SPI_TEST_Load_Slave_TX_Data (1, slave_tx_data, 3); 
	SPI_Write_Data (0, SPI_MASTER, master_tx_data, 3); 
	
	for (delay=0; delay<10000; delay++); 
	
	read_count = 5; 
	SPI_Read_Data (0, SPI_MASTER, slave_rx_data, &read_count); 
	
	cprintf("read_count=%d\r\n", read_count);
	
	for (i=0; i<read_count; i++) cprintf("0x%04X, ", slave_rx_data[i]); 
	cprintf("\r\n"); 
	
#endif 




	//===============================================================
	// SPI TEST #4 : SPI0 = slave, SPI1 = master 
	//				SPI1 --> SPI0 : transmit three bytes
	//				SPI0 --> SPI1 : transmit three bytes
	//
	// DISPLAY --> SPI0 RX data [slave]
	//===============================================================
#if 0	
	UINT32			master_tx_data[8] = {0xA5, 0xA6, 0xA7, 0xA8,  0xA9, 0xAA, 0xAB, 0xAC}; 
	UINT32			slave_tx_data[8] = {0x50, 0x51, 0x52, 0x53,  0x54, 0x55, 0x56, 0x57}; 
	UINT32			slave_rx_data[8]; 
	int 			read_count; 
	int 			i; 
	volatile int	delay; 
			
	
	SPI_TEST_Load_Slave_TX_Data (0, slave_tx_data, 3); 
	SPI_Write_Data (1, SPI_MASTER, master_tx_data, 3); 
	
	for (delay=0; delay<10000; delay++); 
	
	read_count = 5; 
	SPI_Read_Data (0, SPI_SLAVE, slave_rx_data, &read_count); 
	
	cprintf("read_count=%d\r\n", read_count);
	
	for (i=0; i<read_count; i++) cprintf("0x%04X, ", slave_rx_data[i]); 
	cprintf("\r\n"); 
	
#endif 
	
	
	//===============================================================
	// SPI TEST #5 : SPI0 = slave, SPI1 = master 
	//				SPI1 --> SPI0 : transmit three bytes
	//				SPI0 --> SPI1 : transmit three bytes
	//
	// DISPLAY --> SPI1 RX data [master] 
	//===============================================================
#if 1
	UINT32			master_tx_data[8] = {0xA5, 0xA6, 0xA7, 0xA8,  0xA9, 0xAA, 0xAB, 0xAC}; 
	UINT32			slave_tx_data[8] = {0x50, 0x51, 0x52, 0x53,  0x54, 0x55, 0x56, 0x57}; 
	UINT32			slave_rx_data[8]; 
	UINT32 			read_count; 
	int 			i; 
	volatile int	delay; 
				
		
	SPI_TEST_Load_Slave_TX_Data (0, slave_tx_data, 3); 
	SPI_Write_Data (1, SPI_MASTER, master_tx_data, 3); 
		
	for (delay=0; delay<10000; delay++); 
		
	read_count = 5; 
	SPI_Read_Data (1, SPI_MASTER, slave_rx_data, &read_count); 
		
	cprintf("read_count=%d\r\n", read_count);
		
	for (i=0; i<read_count; i++) cprintf("0x%04X, ", slave_rx_data[i]); 
	cprintf("\r\n"); 
		
#endif 


	//
	
	cprintf("SPI test -> run \r\n"); 
	
	return (0);
}



//============================================================================
// @ Name : SPI_TEST_Master_Setting
//
// @ Parameter
//		- spi_no : 0, 1
//		- port_sel : SPI_PORTSEL_NORMAL, SPI_PORTSEL_STAR
//
//
//============================================================================
void SPI_TEST_Master_Setting(int spi_no, int port_sel)
{
	SPI_CONFIG		SPI_config; 

	
	SPI_config.SS_enable = SPI_SS_ENABLE; 
	SPI_config.SS_auto_manual = SPI_SS_AUTOMATIC; 
	
	SPI_config.SS_polarity = SPI_SS_ACTIVE_LOW; 
	//SPI_config.SS_polarity = SPI_SS_ACTIVE_HIGH; 
	
	SPI_config.SS_masking = SPI_SS_NOT_MASKING; 

	SPI_config.msb_lsb_first = SPI_MSB_FIRST; 
	
	//SPI_config.clock_polarity = SPI_CPOL_ACTIVE_HIGH; 
	SPI_config.clock_polarity = SPI_CPOL_ACTIVE_LOW; 
	
	//SPI_config.clock_phase = SPI_CPHA_FRONT_HALF;
	SPI_config.clock_phase = SPI_CPHA_REAR_HALF;

	
	SPI_config.bit_size = SPI_BITSIZE_8_BITS;	

	SPI_config.baudrate = 0x00FF; 

	SPI_config.start_len = 8; 
	SPI_config.burst_len = 8;
	SPI_config.stop_len = 8; 

	SPI_Init (spi_no, SPI_MASTER, port_sel, &SPI_config); 

}


//============================================================================
// @ Name : SPI_TEST_Slave_Setting
//
// @ Parameter
//		- spi_no : 0, 1
//		- port_sel : SPI_PORTSEL_NORMAL, SPI_PORTSEL_STAR
//
//
//============================================================================
void SPI_TEST_Slave_Setting(int spi_no, int port_sel)
{
	SPI_CONFIG		SPI_config; 

	
	SPI_config.SS_enable = SPI_SS_ENABLE; 
	SPI_config.SS_auto_manual = SPI_SS_AUTOMATIC; 
	
	SPI_config.SS_polarity = SPI_SS_ACTIVE_LOW; 
	//SPI_config.SS_polarity = SPI_SS_ACTIVE_HIGH; 
	
	SPI_config.SS_masking = SPI_SS_NOT_MASKING; 

	SPI_config.msb_lsb_first = SPI_MSB_FIRST; 
	
	//SPI_config.clock_polarity = SPI_CPOL_ACTIVE_HIGH; 
	SPI_config.clock_polarity = SPI_CPOL_ACTIVE_LOW; 
	
	//SPI_config.clock_phase = SPI_CPHA_FRONT_HALF; 
	SPI_config.clock_phase = SPI_CPHA_REAR_HALF; 
	
	SPI_config.bit_size = SPI_BITSIZE_8_BITS;	

	SPI_config.baudrate = 0x00FF; 

	SPI_config.start_len = 8; 
	SPI_config.burst_len = 8;
	SPI_config.stop_len = 8; 

	SPI_Init (spi_no, SPI_SLAVE, port_sel, &SPI_config); 

}




//============================================================================
// @ Name : SPI_TEST_Slave_Setting
//
// @ Parameter
//		- spi_no : 0, 1
//		- p_tx_data : address of slave transmission data array
//		- data_count : data count 
//
// @ Return 
//		SPI_TX_BUFFER_SUCCESS
//		SPI_TX_BUFFER_ERROR_WRONG_CHANNEL
//
//============================================================================

int SPI_TEST_Load_Slave_TX_Data (int spi_no, UINT32 *p_tx_data, UINT32 data_count)
{

	SPI_BUFFER			*p_SPI_buffer; 
	int					i; 
	int					status; 

	
	//------------------------------------------------------------------------------------------
	// get base address
	//------------------------------------------------------------------------------------------
	p_SPI_buffer = SPI_Get_BufferAddr (spi_no, SPI_SLAVE, &status); 

	if (status == SPI_CHANNEL_NOT_SUPPORTED)
	{
		return (SPI_TX_BUFFER_ERROR_WRONG_CHANNEL);
	}


	//------------------------------------------------------------------------------------------
	// copy data from write-buffer to SPI-buffer 
	//------------------------------------------------------------------------------------------
	for (i=0; i<data_count; i++)
	{

		p_SPI_buffer->u32TxBuffer[i] = *(p_tx_data + i); 
	}

	p_SPI_buffer->u16TxBuffer_HeadIndex = 0; 
	p_SPI_buffer->u16TxBuffer_TailIndex = data_count; 	



	return (SPI_TX_BUFFER_SUCCESS); 

}

